package jspwiki.plugins;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.log4j.Logger;

import com.ecyrd.jspwiki.WikiContext;
import com.ecyrd.jspwiki.WikiEngine;
import com.ecyrd.jspwiki.attachment.Attachment;
import com.ecyrd.jspwiki.attachment.AttachmentManager;
import com.ecyrd.jspwiki.attachment.DynamicAttachment;
import com.ecyrd.jspwiki.attachment.DynamicAttachmentProvider;
import com.ecyrd.jspwiki.plugin.PluginException;
import com.ecyrd.jspwiki.plugin.WikiPlugin;
import com.ecyrd.jspwiki.providers.ProviderException;

/**
 * @author Francis Novilla
 */
public class UnzipAttachment implements WikiPlugin {

  private static final Logger log = Logger.getLogger(UnzipAttachment.class);

  public static final String PARAM_PAGENAME = "page";
  public static final String PARAM_ATTACHMENT = "attachment";

  /**
   * {@inheritDoc}
   */
  @SuppressWarnings("unchecked")
  public String execute(WikiContext context, Map params) throws PluginException {

    StringBuffer sb = new StringBuffer();
    if (context.getVariable(this.getClass().toString()) == null) {
      context.setVariable(this.getClass().toString(), new Object()); // init

      WikiEngine engine = context.getEngine();
      String attachment = (String) params.get(PARAM_ATTACHMENT);

      try {
        AttachmentManager attMgr = engine.getAttachmentManager();
        Attachment att = attMgr.getAttachmentInfo(attachment);
        InputStream in = attMgr.getAttachmentStream(context, att);
        ZipInputStream zipIn = new ZipInputStream(in);
        ZipEntry zipentry = zipIn.getNextEntry();

        System.out.println("looping");
        while (zipentry != null) {
          // for each entry to be extracted
          String entryName = zipentry.getName();
          System.out.println("entryname " + entryName);

          entryName = entryName.replace('/', '.');
          System.out.println("newEntryname " + entryName);

          sb.append(entryName).append("\n");

          byte[] bytes = new byte[0];
          byte[] buf = new byte[1024];
          int count;
          while ((count = zipIn.read(buf, 0, buf.length)) != -1) {
            bytes = concat(bytes, Arrays.copyOf(buf, count));
          }

          zipIn.closeEntry();

          DynamicAttachment destatt = new DynamicAttachment(context.getEngine(), context.getPage().getName(),
              entryName, new UnzippedAttachmentsProvider(bytes));

          destatt.setCacheable(false);
          destatt.setLastModified(context.getPage().getLastModified());
          attMgr.storeDynamicAttachment(context, destatt);
          zipentry = zipIn.getNextEntry();

        }// while

        zipIn.close();
      } catch (IOException e) {
        log.error(e.getMessage(), e);
        return e.getMessage();
      } catch (ProviderException e) {
        log.error(e.getMessage(), e);
        return e.getMessage();
      }
    }

    return this.getClass().toString() + ":" + sb;
  }

  byte[] concat(byte[] A, byte[] B) {
    byte[] C = new byte[A.length + B.length];
    System.arraycopy(A, 0, C, 0, A.length);
    System.arraycopy(B, 0, C, A.length, B.length);

    return C;
  }

  class UnzippedAttachmentsProvider implements DynamicAttachmentProvider {
    byte[] buf;

    public UnzippedAttachmentsProvider(byte[] buf) {
      this.buf = buf;
    }

    public InputStream getAttachmentData(WikiContext context, Attachment att) throws IOException {
      return new ByteArrayInputStream(buf);
    }
  }

}
